//
//  VSRevealController.m
//  ViewSeer
//
//  Created by LevinYan on 2017/3/21.
//  Copyright © 2017年 LevinYan. All rights reserved.
//

#import <SceneKit/SceneKit.h>
#import "VSRevealController.h"

static const CGFloat kCameraDistance = 10;

typedef NS_ENUM(NSUInteger, BottomButtonIndex){
    
    BottomButtonReset = 0,
    BottomButtonFocus,
    BottomButtonCenter,
    BottomButtonZoomIn,
    BottomButtonZoomOut,
};

@interface VSRevealController ()

@property (nonatomic, strong) SCNScene *scene;
@property (nonatomic, strong) SCNNode *borderNode;
@property (nonatomic, strong) SCNView *scnView;
@property (nonatomic, strong) VSNode *selectedNode;
@property (nonatomic, strong) SCNNode *cameraNode;

@end

@implementation VSRevealController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.scnView = [[SCNView alloc] initWithFrame:self.view.bounds];
    self.scnView.allowsCameraControl = YES;

    [self.view addSubview:self.scnView];
    
    self.scene = [SCNScene scene];
    self.scnView.scene = self.scene;
    
    SCNNode *cameraNode = [SCNNode node];
    cameraNode.camera = [SCNCamera camera];
    cameraNode.constraints = @[[SCNLookAtConstraint lookAtConstraintWithTarget:self.scene.rootNode]];
    cameraNode.position = SCNVector3Make(0, 0, kCameraDistance);
    cameraNode.name = @"camera";
    self.cameraNode = cameraNode;
    
    [self.scene.rootNode addChildNode:cameraNode];
    
    [self initUI];
    
}

- (void)initUI
{
    
    UIButton *topLeftButton = [[UIButton alloc] initWithFrame:CGRectMake(10, 20, 30, 30)];
    [topLeftButton setImage:[UIImage imageNamed:@"VSHierarchy"] forState:UIControlStateNormal];
    [topLeftButton addTarget:self action:@selector(revealControllerLeftTopButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:topLeftButton];
    
    UIButton *topRightButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.bounds.size.width - 30 - 10, 20, 30, 30)];
    [topRightButton setImage:[UIImage imageNamed:@"VSAttribute"] forState:UIControlStateNormal];
    [topRightButton addTarget:self action:@selector(revealControllerrightTopButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:topRightButton];
    
    
    NSUInteger buttonCount = 5;
    CGFloat buttonH = 44;
    NSMutableArray<UIButton*> *buttons = [NSMutableArray array];
    CGFloat width = self.view.bounds.size.width;
    CGFloat buttonW = width/buttonCount;
    for(NSUInteger i = 0; i < buttonCount; i++){
        
        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(i*buttonW, self.view.bounds.size.height - buttonH, buttonW, buttonH)];
        button.tag = i;
        [button addTarget:self action:@selector(bottomButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
        [buttons addObject:button];
        [self.view addSubview:button];
    }
    [buttons[BottomButtonReset] setImage:[UIImage imageNamed:@"VSRestore"] forState:UIControlStateNormal];
    [buttons[BottomButtonFocus] setImage:[UIImage imageNamed:@"VSFocus"] forState:UIControlStateNormal];
    [buttons[BottomButtonCenter] setImage:[UIImage imageNamed:@"VSCenter"] forState:UIControlStateNormal];
    [buttons[BottomButtonZoomIn] setImage:[UIImage imageNamed:@"VSZoomin"] forState:UIControlStateNormal];
    [buttons[BottomButtonZoomOut] setImage:[UIImage imageNamed:@"VSZoomout"] forState:UIControlStateNormal];
    
}
#pragma mark - User Event
- (void)bottomButtonClicked:(UIButton*)button
{
    
    SCNNode *cameraNode =  self.scnView.pointOfView;
    SCNVector3 position = cameraNode.position;
    
    switch (button.tag) {
        case BottomButtonReset:{
            self.scnView.pointOfView = self.cameraNode;
            break;
        }
        case BottomButtonFocus:{
            
            break;
        }
        case BottomButtonCenter:{
            break;
        }
            
        case BottomButtonZoomIn:{
            position.z -= 0.5;
            cameraNode.position = position;

            break;
        }
            
        case BottomButtonZoomOut:{
            position.z += 0.5;
            cameraNode.position = position;

            break;
        }
            
    }
}
- (void)revealControllerLeftTopButtonClicked:(UIButton*)button
{
    
    [self.delegate revealControllerLeftTopButtonClicked];
}

- (void)revealControllerrightTopButtonClicked:(UIButton*)button
{
    [self.delegate revealControllerrightTopButtonClicked];
}



#pragma mark - Render

- (void)renderNodes
{
    NSUInteger level = 0;
    [self renderNode:self.rootNode level:level superNode:self.scene.rootNode];
    
}

- (void)renderNode:(VSNode*)node level:(NSUInteger)level superNode:(SCNNode*)superNode
{
    
    CGFloat scale = 0.008;
    CGRect frame = CGRectMake(node.view.frame.origin.x * scale, node.view.frame.origin.y * scale, node.view.frame.size.width * scale, node.view.frame.size.height * scale);

    CGSize size = frame.size;
    CGPoint center;
    
    if(superNode == self.scene.rootNode){
        center = CGPointZero;
    }
    else{//right-hand to lef-hand coordinate system, and origal is center
        CGPoint oldCenter = CGPointMake(frame.origin.x + size.width/2, frame.origin.y + size.height/2);
        SCNPlane *superPlane = (SCNPlane*)superNode.geometry;
        center = CGPointMake(oldCenter.x - superPlane.width/2,  superPlane.height/2 - oldCenter.y);
    }
    


    SCNPlane *plane = [SCNPlane planeWithWidth:size.width  height:size.height];
    plane.firstMaterial.locksAmbientWithDiffuse = YES;
    plane.firstMaterial.diffuse.contents = [self imageFromLayer:node.view.layer];
    plane.firstMaterial.doubleSided = YES;
    SCNNode *scnNode = [SCNNode nodeWithGeometry:plane];
    scnNode.name = [NSString stringWithFormat:@"%@", @(node.view.tag)];
    scnNode.position = SCNVector3Make(center.x , center.y, 0.2*level);

    [superNode addChildNode:scnNode];
    node.scnNode = scnNode;
    
    for(VSNode *subnode in node.subnodes)
    {
        [self renderNode:subnode level:level + 1 superNode:scnNode];
    }

}


- (void)renderSelectedNode:(SCNNode*)scnNode
{
    [self.borderNode removeFromParentNode];
    
    CGFloat width = ((SCNPlane*)scnNode.geometry).width - 0.02;
    CGFloat height = ((SCNPlane*)scnNode.geometry).height - 0.02;
    
    SCNVector3 positions[] = {
        SCNVector3Make(-width/2, -height/2, 0.0),
        SCNVector3Make(width/2,  -height/2, 0.0),
        SCNVector3Make(width/2,  height/2, 0.0),
        SCNVector3Make(-width/2, height/2, 0.0)
        
        
    };
    
    int indices[] = {0, 1, 1, 2, 2, 3, 3, 0};
    
    SCNGeometrySource *vertexSource = [SCNGeometrySource geometrySourceWithVertices:positions
                                                                              count:sizeof(positions)/sizeof(positions[0])];
    NSData *indexData = [NSData dataWithBytes:indices
                                       length:sizeof(indices)];
    
    SCNGeometryElement *element = [SCNGeometryElement geometryElementWithData:indexData
                                                                primitiveType:SCNGeometryPrimitiveTypeLine
                                                               primitiveCount:4
                                                                bytesPerIndex:sizeof(int)];
    SCNGeometry *border = [SCNGeometry geometryWithSources:@[vertexSource]
                                                  elements:@[element]];
    border.firstMaterial.locksAmbientWithDiffuse = YES;
    border.firstMaterial.diffuse.contents = [UIColor blackColor];
    self.borderNode = [SCNNode nodeWithGeometry:border];
    [scnNode addChildNode:self.borderNode];
}
- (UIImage *)imageFromLayer:(CALayer *)layer
{
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0);
    
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return outputImage;
}
#pragma mark -



- (void)setRootNode:(VSNode *)rootNode
{
    _rootNode = rootNode;
    [self renderNodes];
}

- (void)setSelectedNode:(VSNode *)selectedNode
{
    _selectedNode = selectedNode;
    [self.delegate revealControllerDidSelectedNode:_selectedNode];
    [self renderSelectedNode:selectedNode.scnNode];
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = touches.allObjects.firstObject;
    CGPoint point = [touch locationInView:self.view];
    NSArray<SCNHitTestResult *> *results = [self.scnView hitTest:point options:nil];
    
    if(self.rootNode.scnNode == results.firstObject.node){
        self.selectedNode = self.rootNode;
    }else{
        for(VSNode *node in self.rootNode.allSubnodes){
            
            if(node.scnNode == results.firstObject.node){
                self.selectedNode = node;
                break;
            }
        }
    }
}

@end
